﻿using System;
using System.Windows.Forms;
using SurveySystem.Admin.Screens;
using SurveySystem.Model;

namespace SurveySystem.Admin.Controllers
{
    public class EditSurveyQuestionsController
    {
        private EditSurveyQuestionsForm frm;
        private Survey survey;

        public EditSurveyQuestionsController(Survey s)
        {
            this.survey = s;
            this.frm = new EditSurveyQuestionsForm();

            frm.txtSurveyName.Text = s.Title;

            frm.lvQuestionList.SelectedIndexChanged += new EventHandler(lvQuestionList_SelectedIndexChanged);
            frm.btnAddQuestion.Click += new EventHandler(btnAddQuestion_Click);
            frm.txtQuestionText.TextChanged += new EventHandler(txtQuestionText_TextChanged);
            frm.chkRequired.CheckedChanged += new EventHandler(chkRequired_CheckedChanged);
            frm.chkMultiSelect.CheckedChanged += new EventHandler(chkMultiSelect_CheckedChanged);
            frm.btnDeleteQuestion.Click += new EventHandler(btnDeleteQuestion_Click);
            frm.btnAddAnswer.Click += new EventHandler(btnAddAnswer_Click);
            frm.btnDeleteAnswer.Click += new EventHandler(btnDeleteAnswer_Click);
            frm.txtAnswerText.TextChanged += new EventHandler(txtAnswerText_TextChanged);
            frm.lstAnswers.SelectedIndexChanged += new EventHandler(lstAnswers_SelectedIndexChanged);
            frm.txtAnswerText.Leave += new EventHandler(txtAnswerText_Leave);

            PopulateQuestions();
        }

        #region " Event handlers "
        private void btnAddQuestion_Click(object sender, EventArgs e)
        {
            // add a new, blank question
            Question q = new Question();

            // find the next question number
            int i = 0;
            foreach (Question q2 in survey.Questions)
            {
                if (q2.QuestionNumber > i)
                    i = q2.QuestionNumber;
            }
            q.QuestionNumber = i + 1;

            survey.Questions.Add(q);

            PopulateQuestions();

            // select the last question
            frm.lvQuestionList.SelectedItems.Clear();
            frm.lvQuestionList.SelectedIndices.Add(frm.lvQuestionList.Items.Count - 1);
        }

        private void lvQuestionList_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListView lv = frm.lvQuestionList;

            if (lv.SelectedItems.Count == 0)
                // disable the properties groupbox if nothing selected
                PopulateQuestionPropertiesAndAnswers(null);
            else
            {
                // populate the properties groupbox if a question is selected
                Question q = (Question)lv.SelectedItems[0].Tag;
                PopulateQuestionPropertiesAndAnswers(q);
            }
        }

        private void txtQuestionText_TextChanged(object sender, EventArgs e)
        {
            if (frm.lvQuestionList.SelectedItems.Count == 0)
                return;

            // get the selected question
            Question q = (Question)(frm.lvQuestionList.SelectedItems[0].Tag);

            // update its value
            q.QuestionText = frm.txtQuestionText.Text;

            // update the listview
            frm.lvQuestionList.SelectedItems[0].SubItems[1].Text = q.QuestionText;
        }

        private void chkMultiSelect_CheckedChanged(object sender, EventArgs e)
        {
            if (frm.lvQuestionList.SelectedItems.Count == 0)
                return;

            // get the selected question
            Question q = (Question)(frm.lvQuestionList.SelectedItems[0].Tag);

            // update its value
            q.MultiSelect = frm.chkMultiSelect.Checked;

            // update the listview
            frm.lvQuestionList.SelectedItems[0].SubItems[4].Text = q.MultiSelect ? "Yes" : "No";
        }

        private void chkRequired_CheckedChanged(object sender, EventArgs e)
        {
            if (frm.lvQuestionList.SelectedItems.Count == 0)
                return;

            // get the selected question
            Question q = (Question)(frm.lvQuestionList.SelectedItems[0].Tag);

            // update its value
            q.Required = frm.chkRequired.Checked;

            // update the listview
            frm.lvQuestionList.SelectedItems[0].SubItems[3].Text = q.Required ? "Yes" : "No";
        }

        private void btnDeleteAnswer_Click(object sender, EventArgs e)
        {
            if (frm.lvQuestionList.SelectedItems.Count == 0)
                return;

            if (frm.lstAnswers.SelectedItems.Count == 0)
                return;

            DialogResult res = MessageBox.Show("Are you sure you want to delete this answer? Results may be affected if any have been entered", "Confirm delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (res != DialogResult.Yes)
                return;

            // get the selected question
            Question q = (Question)(frm.lvQuestionList.SelectedItems[0].Tag);

            // get the select answer
            Answer a = (Answer)(frm.lstAnswers.SelectedItem);

            // remove the answer from the question
            q.PossibleAnswers.Remove(a);

            PopulateAnswers(q);

        }

        private void btnAddAnswer_Click(object sender, EventArgs e)
        {
            if (frm.lvQuestionList.SelectedItems.Count == 0)
                return;

            // get the selected question
            Question q = (Question)(frm.lvQuestionList.SelectedItems[0].Tag);

            q.PossibleAnswers.Add(new Answer());

            PopulateAnswers(q);

            // select the last item
            frm.lstAnswers.SelectedItems.Clear();
            frm.lstAnswers.SelectedIndices.Add(frm.lstAnswers.Items.Count - 1);
            frm.txtAnswerText.Focus();
        }

        private void btnDeleteQuestion_Click(object sender, EventArgs e)
        {
            if (frm.lvQuestionList.SelectedItems.Count == 0)
                return;

            DialogResult res = MessageBox.Show("Are you sure you want to delete this question and associated answers? Results may be affected if any have been entered", "Confirm delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (res != DialogResult.Yes)
                return;

            // get the selected question
            Question q = (Question)(frm.lvQuestionList.SelectedItems[0].Tag);

            // remove it from the Question object
            survey.Questions.Remove(q);

            // remove it from the list
            frm.lvQuestionList.Items.RemoveAt(frm.lvQuestionList.SelectedIndices[0]);

            // deselect anything
            frm.lvQuestionList.SelectedItems.Clear();
        }

        private void txtAnswerText_TextChanged(object sender, EventArgs e)
        {
            if (frm.lvQuestionList.SelectedItems.Count == 0)
                return;

            if (frm.lstAnswers.SelectedItems.Count == 0)
                return;

            // get the select answer
            Answer a = (Answer)(frm.lstAnswers.SelectedItem);

            // update its value
            a.AnswerText = frm.txtAnswerText.Text;
        }

        private void lstAnswers_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (frm.lstAnswers.SelectedItems.Count == 0)
            {
                frm.txtAnswerText.Text = "";
                frm.txtAnswerText.Enabled = false;
                frm.btnDeleteAnswer.Enabled = false;
            }
            else
            {
                frm.txtAnswerText.Text = frm.lstAnswers.SelectedItem.ToString();
                frm.txtAnswerText.Enabled = true;
                frm.btnDeleteAnswer.Enabled = true;
            }

        }

        private void txtAnswerText_Leave(object sender, EventArgs e)
        {
            if (frm.lvQuestionList.SelectedItems.Count == 0)
                return;

            // get the selected question
            Question q = (Question)(frm.lvQuestionList.SelectedItems[0].Tag);

            PopulateAnswers(q);
        }

        #endregion

        #region " Form refreshing and populating methods "
        private void PopulateQuestionPropertiesAndAnswers(Question q)
        {
            // if nothing selected, just clear the box and disable it
            if (q == null)
            {
                frm.grpQuestionProperties.Enabled = false;
                frm.txtQuestionText.Text = "";
                frm.chkRequired.Checked = false;
                frm.chkMultiSelect.Checked = false;
                frm.lstAnswers.Items.Clear();
                return;
            }


            frm.grpQuestionProperties.Enabled = true;
            frm.txtQuestionText.Text = q.QuestionText;
            frm.chkRequired.Checked = q.Required;
            frm.chkMultiSelect.Checked = q.MultiSelect;

            PopulateAnswers(q);
        }

        private void PopulateAnswers(Question q)
        {
            // populate the list of answers
            frm.lstAnswers.Items.Clear();
            foreach (Answer a in q.PossibleAnswers)
            {
                frm.lstAnswers.Items.Add(a);
            }
        }

        private void PopulateQuestions()
        {
            ListView lv = frm.lvQuestionList;

            // clear any existing items
            lv.Items.Clear();

            frm.txtAnswerText.Text = "";
            frm.txtQuestionText.Text = "";

            foreach (Question q in survey.Questions)
            {
                ListViewItem l = new ListViewItem();

                l.Text = q.QuestionNumber.ToString();
                l.SubItems.Add(q.QuestionText);
                l.SubItems.Add(q.PossibleAnswers.Count.ToString());
                l.SubItems.Add(q.Required ? "Yes" : "No");
                l.SubItems.Add(q.MultiSelect ? "Yes" : "No");

                l.Tag = q;

                lv.Items.Add(l);

            }
        }
        #endregion

        internal DialogResult ShowDialog()
        {
            return frm.ShowDialog();
        }
    }
}
